import { getPoints } from '@/utils/points.js'
import { EffectManager } from '@/utils/EffectManager';
import { MouseHandler } from '@/utils/MouseHandler';
import store from '@/store'
import { cameraMove } from '@/utils/helper'
import * as THREE from 'three'
// 车辆类
// 场景，摄像机，控制器，车辆模型，车辆数据
export function Car(scene, camera, controls, carModel, carDataObj, carInfo2d) {
  this.scene = scene;
  this.camera = camera;
  this.controls = controls;
  this.carModel = carModel; // 车模型
  this.carDataObj = carDataObj; // 车数据
  this.carInfo2d = carInfo2d; // 车辆信息2d
  this.scene.add(this.carModel)
  this.carModel.scale.set(0.8, 0.8, 0.8)

  this.bindClick() // new Car 的同时，给这辆车订阅点击事件

  // 根据数据里决定停车位名字 => 停车位物体 => 物体的坐标 => 车辆设置到这个坐标上
  // 找到车位 3D 物体
  if (this.carDataObj.car.status !== 2) return
  const parkingSpace = this.scene.getObjectByName(this.carDataObj.parkNum)
  this.carModel.position.copy(parkingSpace.position)
  // 发现车辆是默认朝着 z 轴正方向的，但是我的停车场是歪着的，所以要把车歪过来
  // 上面一排车位号码是奇数位，下面一排偶数位
  if (this.carDataObj.parkNumber % 2 === 0) {
    // 下排车位
    this.carModel.rotation.y = 1.1714 * Math.PI
  } else {
    // 上排车位
    this.carModel.rotation.y = 0.1666 * Math.PI
  }
}


Car.prototype.bindClick = function () {
  // 车辆-订阅点击事件
  MouseHandler.getInstance().addClickMesh(this.carModel, () => {
    this.carInfo2d.visible = true;
    this.carInfo2d.position.copy(this.carModel.position);
    // car.carDataObj.car -> 拿到车辆详细信息对象
    console.log(this.carDataObj.car);
    store.commit("car/setCarInfo", this.carDataObj);

    // 调整摄像机位置
    // 目标：根据你点击的车辆模型物体坐标，相对计算摄像机的位置并移动观察（车辆坐标原点）
    if (this.carDataObj.parkNumber % 2 !== 0) {
      // 上排
      cameraMove(
        this.camera,
        this.controls,
        new THREE.Vector3(
          this.carModel.position.x + 9,
          this.carModel.position.y + 8,
          this.carModel.position.z + 16
        ),
        this.carModel.position
      );
    } else {
      // 下排
      cameraMove(
        this.camera,
        this.controls,
        new THREE.Vector3(
          this.carModel.position.x - 9,
          this.carModel.position.y + 8,
          this.carModel.position.z - 16
        ),
        this.carModel.position
      );
    }
  });
}

// 创建入场车辆 => 运动到进场一体杆前
Car.prototype.moveEnterFormStartToPole = function () {
  return new Promise(resolve => {
    // 目标：3D 物体运动的路径规划
    // 方式1：自己计算几个关键的三维坐标点，然后生成一个曲线路径物体，并分割成指定段数，并返回所有坐标点集合
    // 方式2：根据建模师建好的线段物体，收集对应的坐标点集合
    const points = getPoints(this.scene.getObjectByName(`${this.carDataObj.areaName}_进场路线`));
    console.log(points);

    // 改装成借助渲染循环函数执行汽车运动
    let i = 0
    const fn = () => {
      if (i === points.length - 1) {
        EffectManager.getInstance().removeEffect(fn)
        resolve() // 动画执行完毕，兑现 resolve 状态让外面 await 放行往下走
        return
      }
      const position = points[i++]
      const nextPos = points[i]
      this.carModel.position.copy(position)
      this.carModel.lookAt(nextPos.x, nextPos.y, nextPos.z)
    }
    // 改变本次 fn 调用的 this 指向为你传入进入的参数值
    // fn.bind(this) 会在原地返回一个全新的函数
    EffectManager.getInstance().addEffect(fn)

    // let i = 0
    // const t = setInterval(() => {
    //   if (i === points.length - 1) return clearInterval(t)
    //   // 当前坐标点，下一个坐标点 => 设置车辆的位置和朝向 => 车辆朝向下一个坐标点，车辆位置下一个坐标点
    //   // 车辆朝向下一个坐标点，车辆位置下一个坐标点 => 车辆朝向下一个坐标点，车辆位置下一个坐标点 => 车辆朝向下一个坐标点，车辆位置下一个坐标点 => 车辆朝向下一个坐标点，车辆位置下一个坐标点 => �
    //   const position = points[i++]
    //   const nextPos = points[i]
    //   this.carModel.position.copy(position)
    //   // lookAt 物体 z 正方向观察指定的坐标点
    //   this.carModel.lookAt(nextPos.x, nextPos.y, nextPos.z)

    //   // // 摄像头跟着动
    //   // this.camera.position.set(position.x, position.y + 4, position.z)
    //   // // 因为有轨道控制器控制着摄像机，所以要改变轨道控制的 target 影响摄像机的 lookAt
    //   // // 如果没有轨道控制器，可以用摄像机.lookAt 直接影响摄像机观察的坐标点
    //   // // this.camera.lookAt(nextPos.x, nextPos.y + 4, nextPos.z)
    //   // this.controls.target = new Vector3(nextPos.x, nextPos.y + 4, nextPos.z)
    // }, 10)
  })

}

// 入场车辆从一体杆 => 车位停车
Car.prototype.movePoleToParkingSpace = function () {
  return new Promise(resolve => {
    // 停车位数据拼接，模型里线段物体，获取并转换坐标集合
    // 进场路线物体
    const lineOne = this.scene.getObjectByName(`${this.carDataObj.parkNum}_进场路线`)
    const lineTwo = this.scene.getObjectByName(`${this.carDataObj.parkNum}_倒车入库路线`)
    // 物体 => 坐标集合
    const lineOnePoints = getPoints(lineOne)
    const lineTwoPoints = getPoints(lineTwo)

    let i = 0
    let j = 0
    const fn = () => {
      if (i === lineOnePoints.length - 1) {
        if (j === lineTwoPoints.length - 1) {
          resolve()
          EffectManager.getInstance().removeEffect(fn)
          return
        }
        let lastIndex = j
        const points = lineTwoPoints[++j]
        const nextPos = lineTwoPoints[lastIndex]

        this.carModel.position.copy(points)
        this.carModel.lookAt(nextPos.x, nextPos.y, nextPos.z)
        return
      }
      const points = lineOnePoints[i++]
      const nextPos = lineOnePoints[i]
      this.carModel.position.copy(points)
      this.carModel.lookAt(nextPos.x, nextPos.y, nextPos.z)
    }
    EffectManager.getInstance().addEffect(fn)
  })
}

// 车位出场 -> 一体杆前
Car.prototype.moveParkingSpaceToPole = function () {
  // 找到路线物体
  return new Promise((resolve) => {
    const lx = this.scene.getObjectByName(`${this.carDataObj.parkNum}_出场路线`)
    const points = getPoints(lx)

    let i = 0
    const fn = () => {
      // 先进场
      if (i < points.length - 1) {
        this.carModel.position.copy(points[i++])
        this.carModel.lookAt(points[i])
      } else {
        // 动画完成
        console.log('被移除了')
        resolve()
        EffectManager.getInstance().removeEffect(fn)
        return
      }
    }
    EffectManager.getInstance().addEffect(fn)
  })
}

// 一体杆->出场（动画）
Car.prototype.movePoleToLeavePark = function () {
  return new Promise((resolve) => {
    const lx = this.scene.getObjectByName(`${this.carDataObj.areaName}_出场路线`)
    const points = getPoints(lx)
    let i = 0
    const fn = () => {
      // 先进场
      if (i < points.length - 1) {
        this.carModel.position.copy(points[i++])
        this.carModel.lookAt(points[i])
      } else {
        // 场外路线运动完毕
        resolve()
        EffectManager.getInstance().removeEffect(fn)
        return
      }
    }
    EffectManager.getInstance().addEffect(fn)
  })
}